#include "uart_interface.h"

#include "mem_utils.h"

#include "usart.h"

#define STM32F407_UART	1


#if defined(STM32F407_UART)

static char stm32f407_init(struct uart_device * pdev, unsigned int baud, unsigned char data_bits, unsigned char stop_bits, unsigned char parity);
static char stm32f407_send(struct uart_device * pdev, char *data, unsigned int len, unsigned char timeout);
static char stm32f407_recv(struct uart_device * pdev, char *data, unsigned char timeout);



struct priv_data stm32f407_priv = {
	&huart1
};

struct uart_device stm32f407_dev = {
	.name = "stm32f407_uart",
	.init = stm32f407_init,
	.send = stm32f407_send,
	.recv = stm32f407_recv,
	.priv_data = (struct priv_data *)&stm32f407_priv,
};

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	struct priv_data *temp_priv = stm32f407_dev.priv_data;
	// judge if transmit ok?
	
	// when transmit ok, release the mutex.
	xSemaphoreGiveFromISR(temp_priv->pMutex, NULL);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	struct priv_data *temp_priv = stm32f407_dev.priv_data;
	
	if(huart == temp_priv->pUart)
	{
		
		xQueueSendFromISR(temp_priv->pQueue, &(temp_priv->pData), NULL);
		
		HAL_UART_Receive_IT(temp_priv->pUart, &(temp_priv->pData), 1);
	}
}

static char stm32f407_init(struct uart_device * pdev, unsigned int baud, unsigned char data_bits, unsigned char stop_bits, unsigned char parity)
{
	struct priv_data *temp_priv = pdev->priv_data;
	
	// mutex init
	temp_priv->pMutex = xSemaphoreCreateMutex();
	// queue init
	temp_priv->pQueue = xQueueCreate(20, 1);
	// trigger the first receive interrupt
	HAL_UART_Receive_IT(temp_priv->pUart, &(temp_priv->pData), 1);
	
	return 0;
}
static char stm32f407_send(struct uart_device * pdev, char *data, unsigned int len, unsigned char timeout)
{
	struct priv_data *temp_priv = pdev->priv_data;

	
	HAL_UART_Transmit(temp_priv->pUart, (const uint8_t*)data, len, timeout);
	
	if(pdTRUE == xSemaphoreTake(temp_priv->pMutex, timeout))
		return 0;
	else
		return -1;
}

static char stm32f407_recv(struct uart_device * pdev, char *data, unsigned char timeout)
{
	struct priv_data *temp_priv = pdev->priv_data;

	if(pdTRUE == xQueueReceive(temp_priv->pQueue, data, timeout))
		return 0;
	else
		return -1;
	
	// if do not judge the return num, getting data from the queue will go wrong.
//	xQueueReceive(temp_priv->pQueue, data, timeout);
}

#endif


// global devices
struct uart_device *g_dev[] = {
	&stm32f407_dev,
};


struct uart_device * find_dev(char * name)
{
	unsigned char i = 0;
	
	for(i = 0; i < sizeof(g_dev) / sizeof(g_dev[0]); i++)
	{
		if(mymemcmp((const char*)name, (const char*)g_dev[i]->name, sizeof(g_dev[i]->name)) == 0)
			return g_dev[i];
	}
	
	return (struct uart_device *)0xFFFFFFFF;
}


